package com.example.demo.ctrl.config.threadTest.forkJoin;

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.LongStream;

/**
 * ForkJoin与其他多线程方式耗费时间对比
 * 练习：0到10000000000L累加
 *
 *  我们观察上面可以看出来执行10000000000L的相加操作各自执行完毕的时间不同。观察到当数据很大的时候ForkJoin比普通线程实现有效的多，但是相比之下ForkJoin的实现实在是有点麻烦，这时候Java 8 就为我们提供了一个并行流来实现ForkJoin实现的功能。可以看到并行流比自己实现ForkJoin还要快
 * Java 8 中将并行流进行了优化，我们可以很容易的对数据进行并行流的操作，Stream API可以声明性的通过parallel()与sequential()在并行流与穿行流中随意切换！
 * https://www.cnblogs.com/wzqjy/p/7921063.html
 * https://www.cnblogs.com/hayasi/p/10639994.html
 */
public class ForkJoinWorkDemo {
    public static void main(String[] args) {
        ForkJoinWorkDemo f=new ForkJoinWorkDemo();
        f.test();
        f.test2();
        f.test3();
    }


    public  void test() {
//ForkJoin实现
        long l = System.currentTimeMillis();
        ForkJoinPool forkJoinPool = new ForkJoinPool();//实现ForkJoin 就必须有ForkJoinPool的支持
        ForkJoinTask<Long> task = new ForkJoinWork(0L,10000000000L);//参数为起始值与结束值
        Long invoke = forkJoinPool.invoke(task);
        long l1 = System.currentTimeMillis();
        System.out.println("ForkJoin实现-invoke = " + invoke+"  time: " + (l1-l));
        //invoke = -5340232216128654848  time: 76474
    }

    public void test2(){
//普通线程实现
        Long x = 0L;
        Long y = 10000000000L;
        long l = System.currentTimeMillis();
        for (Long i = 0L; i <= y; i++) {
            x+=i;
        }
        long l1 = System.currentTimeMillis();
        System.out.println("普通线程实现-invoke = " + x+"  time: " + (l1-l));
        //invoke = -5340232216128654848  time: 160939
    }

    public void test3(){
//Java 8 并行流的实现，消耗时间最短
        long l = System.currentTimeMillis();
        long reduce = LongStream.rangeClosed(0, 10000000000L).parallel().reduce(0, Long::sum);
        long l1 = System.currentTimeMillis();
        System.out.println("Java 8 并行流的实现-invoke = " + reduce+"  time: " + (l1-l));
        //invoke = -5340232216128654848  time: 15531
    }

}
